package playtest;
//import java.io.*;
import java.util.*;
import javamoprt.*;
//import java.lang.ref.*;
//import org.aspectj.lang.*;

class ThreeLocXMonitor_Set extends javamoprt.MOPSet {
	protected ThreeLocXMonitor[] elementData;

	public ThreeLocXMonitor_Set(){
		this.size = 0;
		this.elementData = new ThreeLocXMonitor[4];
	}

	public final int size(){
		while(size > 0 && elementData[size-1].MOP_terminated) {
			elementData[--size] = null;
		}
		return size;
	}

	public final boolean add(MOPMonitor e){
		ensureCapacity();
		elementData[size++] = (ThreeLocXMonitor)e;
		return true;
	}

	public final void endObject(int idnum){
		int numAlive = 0;
		for(int i = 0; i < size; i++){
			ThreeLocXMonitor monitor = elementData[i];
			if(!monitor.MOP_terminated){
				monitor.endObject(idnum);
			}
			if(!monitor.MOP_terminated){
				elementData[numAlive++] = monitor;
			}
		}
		for(int i = numAlive; i < size; i++){
			elementData[i] = null;
		}
		size = numAlive;
	}

	public final boolean alive(){
		for(int i = 0; i < size; i++){
			MOPMonitor monitor = elementData[i];
			if(!monitor.MOP_terminated){
				return true;
			}
		}
		return false;
	}

	public final void endObjectAndClean(int idnum){
		int size = this.size;
		this.size = 0;
		for(int i = size - 1; i >= 0; i--){
			MOPMonitor monitor = elementData[i];
			if(monitor != null && !monitor.MOP_terminated){
				monitor.endObject(idnum);
			}
			elementData[i] = null;
		}
		elementData = null;
	}

	public final void ensureCapacity() {
		int oldCapacity = elementData.length;
		if (size + 1 > oldCapacity) {
			cleanup();
		}
		if (size + 1 > oldCapacity) {
			ThreeLocXMonitor[] oldData = elementData;
			int newCapacity = (oldCapacity * 3) / 2 + 1;
			if (newCapacity < size + 1){
				newCapacity = size + 1;
			}
			elementData = Arrays.copyOf(oldData, newCapacity);
		}
	}

	public final void cleanup() {
		int numAlive = 0 ;
		for(int i = 0; i < size; i++){
			ThreeLocXMonitor monitor = (ThreeLocXMonitor)elementData[i];
			if(!monitor.MOP_terminated){
				elementData[numAlive] = monitor;
				numAlive++;
			}
		}
		for(int i = numAlive; i < size; i++){
			elementData[i] = null;
		}
		size = numAlive;
	}

	public final void event_locx(Car c) {
		int numAlive = 0 ;
		for(int i = 0; i < this.size; i++){
			ThreeLocXMonitor monitor = (ThreeLocXMonitor)this.elementData[i];
			if(!monitor.MOP_terminated){
				elementData[numAlive] = monitor;
				numAlive++;

				monitor.Prop_1_event_locx(c);
				if(monitor.Prop_1_Category_match) {
					monitor.Prop_1_handler_match(c);
				}
			}
		}
		for(int i = numAlive; i < this.size; i++){
			this.elementData[i] = null;
		}
		size = numAlive;
	}

	public final void event_locy(Car c) {
		int numAlive = 0 ;
		for(int i = 0; i < this.size; i++){
			ThreeLocXMonitor monitor = (ThreeLocXMonitor)this.elementData[i];
			if(!monitor.MOP_terminated){
				elementData[numAlive] = monitor;
				numAlive++;

				monitor.Prop_1_event_locy(c);
				if(monitor.Prop_1_Category_match) {
					monitor.Prop_1_handler_match(c);
				}
			}
		}
		for(int i = numAlive; i < this.size; i++){
			this.elementData[i] = null;
		}
		size = numAlive;
	}
}

class ThreeLocXMonitor extends javamoprt.MOPMonitor implements Cloneable, javamoprt.MOPObject {
	public Object clone() {
		try {
			ThreeLocXMonitor ret = (ThreeLocXMonitor) super.clone();
			return ret;
		}
		catch (CloneNotSupportedException e) {
			throw new InternalError(e.toString());
		}
	}

	int Prop_1_state;
	static final int Prop_1_transition_locx[] = {2, 4, 3, 1, 4};;
	static final int Prop_1_transition_locy[] = {0, 4, 0, 0, 4};;

	boolean Prop_1_Category_match = false;

	public ThreeLocXMonitor () {
		Prop_1_state = 0;

	}

	public final void Prop_1_event_locx(Car c) {
		MOP_lastevent = 0;

		Prop_1_state = Prop_1_transition_locx[Prop_1_state];
		Prop_1_Category_match = Prop_1_state == 1;
	}

	public final void Prop_1_event_locy(Car c) {
		MOP_lastevent = 1;

		Prop_1_state = Prop_1_transition_locy[Prop_1_state];
		Prop_1_Category_match = Prop_1_state == 1;
	}

	public final void Prop_1_handler_match (Car c){
		{
			System.out.println("Caught 3 sequence of straight locX's!");
		}

	}

	public final void reset() {
		MOP_lastevent = -1;
		Prop_1_state = 0;
		Prop_1_Category_match = false;
	}

	public javamoprt.ref.MOPWeakReference MOPRef_c;

	//alive_parameters_0 = [Car c]
	public boolean alive_parameters_0 = true;

	public final void endObject(int idnum){
		switch(idnum){
			case 0:
			alive_parameters_0 = false;
			break;
		}
		switch(MOP_lastevent) {
			case -1:
			return;
			case 0:
			//locx
			//alive_c
			if(!(alive_parameters_0)){
				MOP_terminated = true;
				return;
			}
			break;

			case 1:
			//locy
			//alive_c
			if(!(alive_parameters_0)){
				MOP_terminated = true;
				return;
			}
			break;

		}
		return;
	}

}

public aspect CarCallSequence implements javamoprt.MOPObject {
	javamoprt.map.MOPMapManager CreationMapManager;
	public CarCallSequence(){
		CreationMapManager = new javamoprt.map.MOPMapManager();
		CreationMapManager.start();
	}

	// Declarations for the Lock
	static Object Creation_MOPLock = new Object();

	static boolean ThreeLocX_activated = false;

	// Declarations for Indexing Trees
	static javamoprt.map.MOPBasicRefMapOfMonitor ThreeLocX_c_Map = new javamoprt.map.MOPBasicRefMapOfMonitor(0);
	static javamoprt.ref.MOPWeakReference ThreeLocX_c_Map_cachekey_0 = javamoprt.map.MOPBasicRefMapOfMonitor.NULRef;
	static ThreeLocXMonitor ThreeLocX_c_Map_cachenode = null;

	// Trees for References
	static javamoprt.map.MOPRefMap Creation_Car_RefMap = ThreeLocX_c_Map;

	pointcut MOP_CommonPointCut() : !within(javamoprt.MOPObject+) && !adviceexecution();
	pointcut ThreeLocX_locx(Car c) : (call(* Car.setLocX(int)) && target(c)) && MOP_CommonPointCut();
	after (Car c) : ThreeLocX_locx(c) {
		ThreeLocX_activated = true;
		synchronized(Creation_MOPLock) {
			ThreeLocXMonitor mainMonitor = null;
			javamoprt.map.MOPMap mainMap = null;
			javamoprt.ref.MOPWeakReference TempRef_c;

			// Cache Retrieval
			if (c == ThreeLocX_c_Map_cachekey_0.get()) {
				TempRef_c = ThreeLocX_c_Map_cachekey_0;

				mainMonitor = ThreeLocX_c_Map_cachenode;
			} else {
				TempRef_c = ThreeLocX_c_Map.getRef(c);
			}

			if (mainMonitor == null) {
				mainMap = ThreeLocX_c_Map;
				mainMonitor = (ThreeLocXMonitor)mainMap.getNode(TempRef_c);

				if (mainMonitor == null) {
					mainMonitor = new ThreeLocXMonitor();

					mainMonitor.MOPRef_c = TempRef_c;

					ThreeLocX_c_Map.putNode(TempRef_c, mainMonitor);
				}

				ThreeLocX_c_Map_cachekey_0 = TempRef_c;
				ThreeLocX_c_Map_cachenode = mainMonitor;
			}

			mainMonitor.Prop_1_event_locx(c);
			if(mainMonitor.Prop_1_Category_match) {
				mainMonitor.Prop_1_handler_match(c);
			}
		}
	}

	pointcut ThreeLocX_locy(Car c) : (call(* Car.setLocY(int)) && target(c)) && MOP_CommonPointCut();
	after (Car c) : ThreeLocX_locy(c) {
		ThreeLocX_activated = true;
		synchronized(Creation_MOPLock) {
			ThreeLocXMonitor mainMonitor = null;
			javamoprt.map.MOPMap mainMap = null;
			javamoprt.ref.MOPWeakReference TempRef_c;

			// Cache Retrieval
			if (c == ThreeLocX_c_Map_cachekey_0.get()) {
				TempRef_c = ThreeLocX_c_Map_cachekey_0;

				mainMonitor = ThreeLocX_c_Map_cachenode;
			} else {
				TempRef_c = ThreeLocX_c_Map.getRef(c);
			}

			if (mainMonitor == null) {
				mainMap = ThreeLocX_c_Map;
				mainMonitor = (ThreeLocXMonitor)mainMap.getNode(TempRef_c);

				if (mainMonitor == null) {
					mainMonitor = new ThreeLocXMonitor();

					mainMonitor.MOPRef_c = TempRef_c;

					ThreeLocX_c_Map.putNode(TempRef_c, mainMonitor);
				}

				ThreeLocX_c_Map_cachekey_0 = TempRef_c;
				ThreeLocX_c_Map_cachenode = mainMonitor;
			}

			mainMonitor.Prop_1_event_locy(c);
			if(mainMonitor.Prop_1_Category_match) {
				mainMonitor.Prop_1_handler_match(c);
			}
		}
	}

}
